import os
import traceback
from PyQt4.QtGui import *
from S3D.Util import Workspace
from S3D import QtHelper, XmlHelper, Sound

from S3D.Tools.Sound.BatchEditor.UI.MainWindow import Ui_MainWindow

TITLE_ICON      = QtHelper.loadIcon("SoundBatchEditor.ico")
RUN_ICON        = QtHelper.loadCommonIcon(r"Pretty Office 5\Start.ico")

ACTIONS = [
    ("Set", lambda val, prop: prop),
    ("Add", lambda val, prop: str(float(prop) + float(val))),
]

PROPERTIES = Sound.EVENT_PROPERTIES

class MainWindow(QMainWindow):
    def __init__(self, config):
        super(MainWindow, self).__init__()

        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)
        self.setWindowIcon(TITLE_ICON)
        self.ui.runBtn.setIcon(RUN_ICON)

        self.cfg = config

        self.initControls()

        self.show()

    @property
    def workspace(self):
        try:
            return self.workspaces.index(self.cfg.workspace)
        except ValueError:
            return 0

    @workspace.setter
    def workspace(self, index):
        self.cfg.workspace = self.workspaces[index]
        Workspace.setWorkspace(self.cfg.workspace)

    def initControls(self):
        self.dataBind = QtHelper.DataBind()

        # workspace
        self.workspaces = Workspace.getWorkspaceList()
        self.ui.workspaceBox.addItems(self.workspaces)

        for index, name in enumerate(self.workspaces):
            self.ui.workspaceBox.setItemIcon(index, QtHelper.loadWorkspaceIcon(name))

        self.workspace = self.workspace # choose default workspace if needed
        self.dataBind.bindIndex(self.ui.workspaceBox, self, "workspace")

        # project path
        self.dataBind.bindText(self.ui.projectPath, self.cfg, "projectPath")

        # current parameter
        self.ui.propertyBox.addItems(QtHelper.translateTupleList(self, PROPERTIES))
        self.dataBind.bindIndex(self.ui.propertyBox, self.cfg, "property")

        # value
        self.dataBind.bindText(self.ui.valueEdit, self.cfg, "value")

        # action
        self.ui.actionBox.addItems(QtHelper.translateTupleList(self, ACTIONS))
        self.dataBind.bindIndex(self.ui.actionBox, self.cfg, "action")

        # events list
        self.dataBind.bindText(self.ui.eventsListPath, self.cfg, "eventsListPath")
        self.dataBind.bindCheck(self.ui.useEventsListCheck, self.cfg, "useEventsList")

        self.dataBind.updateValues()

    def onBrowseProject(self):
        sounds_dir = Workspace.getRecordWs("sound_src_dir")
        path = QFileDialog.getOpenFileName(self, self.tr("Browse FMOD Project"),
                                             directory=sounds_dir,
                                             filter=self.tr("FMOD Projects (*.fdp);;All files (*.*)"))
        if not path:
            return

        self.ui.projectPath.setText(path)

    def onBrowseEventsList(self):
        sounds_dir = Workspace.getRecordWs("sound_src_dir")
        path = QFileDialog.getOpenFileName(self, self.tr("Browse events list"), directory=sounds_dir)
        if not path:
            return

        self.ui.eventsListPath.setText(path)

    def onRun(self):
        if not os.access(self.cfg.projectPath, os.R_OK):
            QMessageBox.warning(self, self.tr("Failed to convert"), self.tr("FMOD project file could not be read:\n\n%1").arg(self.cfg.projectPath), QMessageBox.Ok)
            return

        if not os.access(self.cfg.projectPath, os.W_OK):
            QMessageBox.warning(self, self.tr("Failed to convert"), self.tr("FMOD project file is readonly:\n\n%1").arg(self.cfg.projectPath), QMessageBox.Ok)
            return

        if self.cfg.useEventsList and not os.access(self.cfg.eventsListPath, os.R_OK):
            QMessageBox.warning(self, self.tr("Failed to convert"), self.tr("Events list file could not be read:\n\n%1").arg(self.cfg.eventsListPath), QMessageBox.Ok)
            return

        _, property = PROPERTIES[self.cfg.property]
        _, action   = ACTIONS[self.cfg.action]

        self.ui.runBtn.setEnabled(False)

        try:
            QtHelper.qApp.processEvents()

            eventsList = None
            if self.cfg.useEventsList:
                print("Loading %s" % self.cfg.eventsListPath)
                eventsList = set()
                with open(self.cfg.eventsListPath, "r") as f:
                    for line in f.readlines():
                        eventsList.add(line.strip().lower())

            print("Loading %s" % self.cfg.projectPath)
            doc = XmlHelper.parseFile(self.cfg.projectPath)

            QtHelper.qApp.processEvents()

            print("Processing...")
            count = 0
            for event in doc.getElementsByTagName("event"):
                # filter by events list
                if eventsList is not None:
                    name = event.getValue("name")
                    if name not in eventsList:
                        continue

                count += 1
                prop = event.getChild(property)
                prop.setText(action(prop.getText(), self.cfg.value))

            QtHelper.qApp.processEvents()

            print("Saving...")
            with open(self.cfg.projectPath, "w") as f:
                doc.writeXml(f)

            print("%d items processed." % count)
            print("Done.")

            QMessageBox.information(self, self.tr("Success"), self.tr("Batch operation complete."), QMessageBox.Ok)
        except Exception, e:
            message = e.message or traceback.format_exc()
            QMessageBox.warning(self, self.tr("Failed"), self.tr("Batch editor failed to process file:\n\n%1").arg(message), QMessageBox.Ok)
            traceback.print_exc()
        finally:
            self.ui.runBtn.setEnabled(True)
